import PubSub from "pubsub-js"
import moment from "moment"
import { removeArrItem, deBounce, formatSingerAndAlbum, randomInt } from "./utils/util"
import { reqSongUrl, reqSongDetail, reqLikeSongId, reqSongComment } from "./request/song"

let db_getSongUrl: any, db_getSongDetail: any, db_getSongComment: any

App<options>({
  globalData: {
    song: {
      //用于保存当前播放歌曲信息，是所有页面的底部playerBar同步数据的根源
      songName: "未有歌曲在播放",
      imgUrl: "http://bpic.588ku.com/element_water_img/18/07/10/5790030b1e1e57b0548d43a2216a9bbe.jpg",
      songId: 0,
      isLike: false,
      singers: "", //歌手名,格式化后
      album: "", //专辑名
      dt: "00:00", // 当前歌曲时长
      comment: "",
    },
    songUrl: "",
    //歌曲状态
    isPlay: false, //当前歌曲是否在播放
    progress: 0, //当前播放百分比
    playMode: "roll", //播放模式，默认为循环播放

    currentPlayListId: 0, //! 当前正在播放的歌单或专辑的id,作为标识,避免主动点击播放同一歌单时重新赋值
    songListIds: [], //! 作为歌单使用,存放一系列的songId

    ids: [0], //用于保存歌单页面的ids，避免每次进入歌单页面都重复发送请求。初始化1个元素为0表示还没被赋值
  },

  onLaunch() {
    //设置并播放歌曲
    const bgm = wx.getBackgroundAudioManager()

    //创建防抖函数
    db_getSongUrl = deBounce(reqSongUrl, 300, true)
    db_getSongDetail = deBounce(reqSongDetail, 300, true)
    db_getSongComment = deBounce(reqSongComment, 300, true)

    this.getIds()

    PubSub.subscribe("playSong", async (_, { songId, openPlayer = true }) => {
      //请求歌曲播放地址

      const { songs } = await (db_getSongDetail as typeof reqSongDetail)(songId)
      const { name, ar, al } = songs[0]
      PubSub.publish("setPlayBar", { songName: name, imgUrl: al.picUrl })

      const { data } = await (db_getSongUrl as typeof reqSongUrl)(songId)
      const url = data[0].url

      bgm.title = name
      bgm.epname = " - " + al.name
      bgm.coverImgUrl = al.picUrl
      bgm.singer = formatSingerAndAlbum(ar)

      this.globalData.song = {
        songId,
        songName: name,
        album: al.name,
        imgUrl: al.picUrl,
        singers: formatSingerAndAlbum(ar),
        isLike: this.globalData.ids.includes(songId),
        dt: "",
        comment: "",
      }
      this.globalData.songUrl = url || ""
      this.globalData.isPlay = true

      // 如果当前页已经在player，则不重复打开player了，预留一个openPlayer字段，判断本次执行是否需要打开player
      const pages = getCurrentPages()
      if (openPlayer && !pages[pages.length - 1].route.includes("player")) {
        wx.navigateTo({
          url: "/pages/player/player",
        })
      }

      //!如果给bgm空间src赋值空串的话，实际上会赋值失败，再次点击播放将会还是上一首歌曲，所以这里直接关停
      //! 但是这里太坑了，在开发者工具中能正常关停，但真机测试里即使调用了stop，也是会自动播放之前能播的那首
      if (url === null) {
        bgm.stop()
        //如果是这种情况，就触发一次progress，让player页面内的内容能够更新
        PubSub.publish("progress", {
          time: "00:00",
          progress: 0,
          dt: "00:00",
        })

        wx.showModal({
          title: "该曲目无法免费播放",
          content: name,
          confirmText: "下一首",
          success({ confirm }) {
            confirm && PubSub.publish("changeSong", { type: "next" })
          },
        })
        PubSub.publish("pauseSong")
      } else {
        bgm.src = url
      }

      const { total } = await (db_getSongComment as typeof reqSongComment)(songId)
      if (total > 10000) {
        this.globalData.song.comment = "1w+"
      } else if (total > 999 && total <= 10000) {
        this.globalData.song.comment = "999+"
      } else {
        this.globalData.song.comment = total.toString()
      }
    })

    //设置歌单：type表示这个歌单data的类型，考虑到不同类型对于接收到data的处理逻辑有所不同，就预留一个字段
    //但大多数情况都是传入一个数组，数组中的每一项都有id字段，遍历存储这个歌单的所有songId
    //id字段，表示这个歌单的唯一标识
    PubSub.subscribe("setPlaylist", (_, { type, data, id }) => {
      // 如果唯一标识没有变,就不执行了,避免点击同一个歌单重复遍历浪费性能
      if (this.globalData.currentPlayListId === id) return

      if (type === "ablum") {
        //!当data类型特殊的时候，根据type来分辨对data的提取songId逻辑
        // ....
        // return
      }

      this.globalData.currentPlayListId = id
      this.globalData.songListIds = data.map((item: any) => item.id)
    })

    //上一首下一首逻辑
    PubSub.subscribe("changeSong", (_, { type, isOrgin = false }) => {
      const { playMode, songListIds, songUrl, song } = this.globalData
      const currentIndex = songListIds.indexOf(song.songId)
      let target: number

      //在单曲循环下，歌曲正常播放结束才会重新播放，如果是手动点击上一曲下一曲就还是会切歌
      if (playMode === "single" && isOrgin) {
        bgm.src = songUrl!
        return
      }

      if (playMode === "random") {
        target = randomInt(0, songListIds.length - 1)
      } else if (type === "next") {
        target = currentIndex === songListIds.length - 1 ? 0 : currentIndex + 1
      } else {
        target = currentIndex === 0 ? songListIds.length - 1 : currentIndex - 1
      }
      PubSub.publish("playSong", { songId: songListIds[target] })
    })

    //暂停歌曲
    PubSub.subscribe("pauseSong", (_, isOrgin: boolean) => {
      //isOrgin表示这个事件是否由bgm控件本身发起,而不是我们自己的控制器
      if (!isOrgin) bgm.pause()
      this.globalData.isPlay = false
    })

    //恢复播放歌曲
    PubSub.subscribe("restartSong", (_, isOrign: boolean = false) => {
      if (!isOrign) return
      bgm.play()
      this.globalData.isPlay = true
    })

    PubSub.subscribe("changeMode", (_, mode: playModeModel) => {
      this.globalData.playMode = mode
    })

    bgm.onPlay(() => {
      PubSub.publish("restartSong", true)
    })

    bgm.onPause(() => {
      PubSub.publish("pauseSong", true)
    })

    bgm.onEnded(() => {
      PubSub.publish("changeSong", { type: "next", isOrgin: true })
    })

    bgm.onNext(() => {
      //点击原生bgm控件才会触发
      PubSub.publish("changeSong", { type: "next" })
    })

    bgm.onPrev(() => {
      //点击原生bgm控件才会触发
      PubSub.publish("changeSong", { type: "next" })
    })

    bgm.onTimeUpdate(() => {
      let progress = (bgm.currentTime / bgm.duration) * 100
      //当进度满了会是NaN
      this.globalData.song.dt = moment(bgm.duration * 1000).format("mm:ss")

      PubSub.publish("progress", {
        time: moment(bgm.currentTime * 1000).format("mm:ss"),
        progress: progress || 100,
        dt: moment(bgm.duration * 1000).format("mm:ss"),
      })
    })

    //*---------------------------------------------------

    PubSub.subscribe("setIds", this.getIds)

    PubSub.subscribe("changeIds", (_, type: 1 | 0) => {
      //type: 1代表新增喜欢，0代表移除喜欢
      const { songId } = this.globalData.song
      if (type) {
        this.globalData.song.isLike = true
        this.globalData.ids.push(songId)
      } else {
        this.globalData.song.isLike = false
        removeArrItem(this.globalData.ids, songId)
      }
    })
  },

  async getIds() {
    //获取用户喜欢的歌曲的id列表
    const uid = wx.getStorageSync("uid")
    if (uid) {
      const { ids } = await reqLikeSongId(uid)
      this.globalData.ids = ids
    }
  },
})

export interface SongModel {
  songName: string
  imgUrl: string
  songId: number
  singers: string
  album: string
  dt: string
  isLike: boolean
  comment: string
}

export type playModeModel = "roll" | "single" | "random"

interface options {
  globalData: {
    song: SongModel

    songUrl: string | null

    isPlay: boolean
    progress: number
    playMode: playModeModel

    ids: number[]
    songListIds: number[]
    currentPlayListId: number
  }
  getIds: () => void
}
